package cn.shop.admin.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.shop.admin.common.async.LogAsync;
import cn.shop.admin.common.util.IpUtil;
import cn.shop.admin.entity.backLogModule.BackLog;
import cn.shop.admin.entity.backPermissionModule.BackPermission;
import cn.shop.admin.entity.backUserModule.BackUser;
import cn.shop.admin.service.BackPermissionService;
import cn.shop.admin.service.BackUserService;
import cn.shop.admin.service.IpWhitelistService;
import cn.shop.base.UserInfoForSession;
import cn.shop.transcation.ipWhitelistModule.entity.IpWhitelist;
import cn.shop.transcation.login.LoginInfoReq;
import cn.shop.utils.ApiResult;
import cn.shop.utils.constant.Constant;
import cn.shop.utils.enums.OperationType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 登录 前端控制器
 *
 * @author jzw
 * @since 2021-11-02 13:37
 */
@RestController
@Validated
@RequestMapping("/api/v1/certification")
public class LoginController {

	@Resource
	private BackUserService backUserService;

	@Resource
	private IpWhitelistService ipWhitelistService;

	@Resource
	private BackPermissionService backPermissionService;

	@Resource
	private LogAsync logAsync;

	/**
	 * 登录
	 *
	 * @param loginInfoReq 存放账号和密码
	 * @return cn.shop.utils.ApiResult<java.util.Map < java.lang.String, java.lang.Object>> 返回sessionid
	 * @author jzw
	 * @since 2021/11/2 14:11
	 */
	@PostMapping("login")
	public ApiResult<Map<String, Object>> login(@Validated @RequestBody LoginInfoReq loginInfoReq) {
		SaSession tokenSession = StpUtil.getTokenSession();
		Object attribute = tokenSession.get(Constant.CAPTCHA_SESSION_KEY);
		if (attribute == null) {
			return ApiResult.fail("验证码已失效,请刷新页面后重试!");
		}
		if (!StrUtil.equalsIgnoreCase((CharSequence) attribute, loginInfoReq.getCode())) {
			return ApiResult.fail("验证码不正确!");
		}
		tokenSession.delete(Constant.CAPTCHA_SESSION_KEY);
		LambdaQueryWrapper<BackUser> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(BackUser::getAccount, loginInfoReq.getAccount()).eq(BackUser::getEnable, true);
		BackUser backUser = backUserService.getOne(wrapper);
		if (backUser == null) {
			return ApiResult.fail("账户或密码错误");
		}
		//判断当前登录是否在白名单内
		LambdaQueryWrapper<IpWhitelist> ipWhitelistLambdaQueryWrapper = Wrappers.lambdaQuery();
		ipWhitelistLambdaQueryWrapper.eq(IpWhitelist::getUserId, backUser.getId());
		List<IpWhitelist> ipWhitelistList = ipWhitelistService.list(ipWhitelistLambdaQueryWrapper);
		String clientIp = IpUtil.getClientIp();
		if (ipWhitelistList.size() > 0) {
			boolean b = ipWhitelistList.stream().noneMatch(e -> e.getIp().equals(clientIp));
			if (b) {
				return ApiResult.fail("当前设备无法登录");
			}
		}
		String password = backUser.getPassword();
		Assert.notBlank(password, "密码不能为空");
		boolean b = DigestUtil.bcryptCheck(loginInfoReq.getPassword(), password);
		if (b) {
			Long backUserId = backUser.getId();
			StpUtil.login(backUserId);
			String account = backUser.getAccount();
			String name = backUser.getName();
			StpUtil.getSession().set(Constant.USER, new UserInfoForSession(backUserId, account, name));
			BackLog backLog = new BackLog();
			backLog.setCreateId(backUserId);
			backLog.setAccount(account);
			backLog.setDetails(StrUtil.format("登录成功,账户 : {} , 登录ip : {}", account, clientIp));
			backLog.setName(name);
			backLog.setType(OperationType.LOGIN);
			logAsync.operationLog(backLog);
			return ApiResult.success(Collections.singletonMap("token", StpUtil.getTokenValue()));
		}
		return ApiResult.fail("账号或密码错误");
	}

	/**
	 * 获取验证码
	 *
	 * @author jzw
	 * @since 2021/11/4 14:03
	 */
	@GetMapping("verificationCode")
	public void verificationCode(HttpServletResponse response) {
		backUserService.verificationCode(response);
	}
	// @GetMapping("verificationCode")
	// public ApiResult<Dict> verificationCode(@RequestParam(required = false) String token) {
	// 	return ApiResult.success(backUserService.verificationCode(token));
	// }

	/**
	 * 获取当前登录人的页面权限
	 *
	 * @author jy
	 * @since 2022/1/18 10:45
	 */
	@GetMapping("/permission")
	public ApiResult<List<String>> getPermissions() {
		return ApiResult.success(backPermissionService.getAllPermissionUrlByUserId());
	}

	/**
	 * 获取当前登录人的按钮权限
	 *
	 * @author jy
	 * @since 2022/1/18 10:46
	 */
	@GetMapping("/btnPermission")
	public ApiResult<List<String>> getBtnPermission() {
		return ApiResult.success(backPermissionService.getAllBtnPermissionByUserId());
	}

	/**
	 * 获取菜单
	 *
	 * @author jzw
	 * @since 2021/11/4 14:03
	 */
	@GetMapping("menu")
	public ApiResult<List<BackPermission>> menu() {
		return ApiResult.success(backPermissionService.allPermissionTreeByUserId(StpUtil.getLoginIdAsLong()));
	}

	/**
	 * 登出
	 *
	 * @return cn.shop.utils.ApiResult<java.util.Map < java.lang.String, java.lang.Object>>
	 * @author jzw
	 * @since 2021/11/2 14:11
	 */
	@GetMapping("logout")
	public ApiResult<Map<String, Object>> logout() {
		StpUtil.logout();
		return ApiResult.success();
	}

	/**
	 * 验证是否登录
	 *
	 * @return cn.shop.utils.ApiResult<java.util.Map < java.lang.String, java.lang.Object>>
	 * @author jzw
	 * @since 2021/11/2 14:11
	 */
	@GetMapping("checkLogin")
	public ApiResult<Map<String, Object>> checkLogin() {
		return ApiResult.success(Collections.singletonMap("res", StpUtil.isLogin()));
	}


}
